package org.cmisarium.xcmis.fsprovider;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.xcmis.spi.BaseContentStream;
import org.xcmis.spi.CmisConstants;
import org.xcmis.spi.ContentStream;
import org.xcmis.spi.DocumentData;
import org.xcmis.spi.NameConstraintViolationException;
import org.xcmis.spi.PolicyData;
import org.xcmis.spi.StorageException;
import org.xcmis.spi.TypeManager;
import org.xcmis.spi.UpdateConflictException;
import org.xcmis.spi.VersioningException;
import org.xcmis.spi.model.AccessControlEntry;
import org.xcmis.spi.model.Property;
import org.xcmis.spi.model.impl.StringProperty;
import org.xcmis.spi.utils.MimeType;

public class DocumentDataImpl extends ObjectDataImpl implements DocumentData
{

   private static final MimeTypeResolver resolver = new MimeTypeResolver();
//   static
//   {
//      resolver.setDefaultMimeType("binary/octet-stream");
//   }

   private String mimeType;

   public DocumentDataImpl(File file, String rootPath, TypeManager typeManager)
   {
      super(file, rootPath, typeManager);
      mimeType = resolver.getMimeType(file.getName());
   }

   public ContentStream getContentStream()
   {

      FileInputStream is = null;
      try
      {
         is = new FileInputStream(file);
         if (is.available() <= 0)
            return null;
      }
      catch (IOException e)
      {
         e.printStackTrace();
         return null;
      }

      return new BaseContentStream(is, file.length(), file.getName(), MimeType.fromString(mimeType));
   }

   public void setContentStream(ContentStream contentStream) throws IOException, UpdateConflictException,
      VersioningException, StorageException
   {
      writeContent(contentStream);
   }

   void writeContent(ContentStream contentStream) throws IOException
   {
      FileOutputStream fos = new FileOutputStream(file);
      InputStream is;
      if (contentStream != null)
         is = contentStream.getStream();
      else
         is = new ByteArrayInputStream(new String("").getBytes());
      int bytes = -1;
      byte[] buffer = new byte[2048];
      while ((bytes = is.read(buffer)) != -1)
      {
         fos.write(buffer, 0, bytes);
      }
      fos.flush();
   }

   public String getContentStreamMimeType()
   {

      return mimeType;
   }

   public Map<String, Property<?>> getProperties()
   {

      Map<String, Property<?>> props = super.getProperties();
      props.put(CmisConstants.CONTENT_STREAM_MIME_TYPE, new StringProperty(CmisConstants.CONTENT_STREAM_MIME_TYPE,
         CmisConstants.CONTENT_STREAM_MIME_TYPE, CmisConstants.CONTENT_STREAM_MIME_TYPE,
         CmisConstants.CONTENT_STREAM_MIME_TYPE, getContentStreamMimeType()));
      return props;

   }

   public String getVersionLabel()
   {
      return null;
   }

   public String getVersionSeriesCheckedOutBy()
   {
      return null;
   }

   public String getVersionSeriesCheckedOutId()
   {
      return null;
   }

   public String getVersionSeriesId()
   {
      return getObjectId();
   }

   public boolean hasContent()
   {
      return file.length() > 0;
   }

   public boolean isLatestMajorVersion()
   {
      return true;
   }

   public boolean isLatestVersion()
   {
      return true;
   }

   public boolean isMajorVersion()
   {
      return true;
   }

   public boolean isPWC()
   {
      throw new UnsupportedOperationException();
   }

   public boolean isVersionSeriesCheckedOut()
   {
      throw new UnsupportedOperationException();
   }

   public void cancelCheckout() throws StorageException
   {
      throw new UnsupportedOperationException();
   }

   public DocumentData checkin(boolean arg0, String arg1, Map<String, Property<?>> arg2, ContentStream arg3,
      List<AccessControlEntry> arg4, Collection<PolicyData> arg5) throws NameConstraintViolationException,
      UpdateConflictException, StorageException
   {
      throw new UnsupportedOperationException();
   }

   public DocumentData checkout()
   {
      throw new UnsupportedOperationException();
   }

}
